﻿#if (WINDOWS_PHONE == false) && (SILVERLIGHT == FALSE)

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Reactive.Linq;
using System.Runtime.Serialization.Json;
using Polenter.Serialization;
using SoTools.Communicator.Messages;

namespace SoTools.Communicator
{
	public sealed partial class Communicator
	{
		public void Publish(BaseMessage message)
		{
			using (var ms = new MemoryStream())
			{
				var client = new UdpClient();

				var serializer = new SharpSerializer(true);
				serializer.Serialize(message, ms);

				ms.Flush();
				ms.Position = 0;
				var buffer = new byte[ms.Length];
				ms.Read(buffer, 0, buffer.Length);

				client.Send(buffer, buffer.Length, new IPEndPoint(_multicastAddress, _multicastPort));
			}
		}

		public IObservable<T> GenerateObservable<T>() where T : BaseMessage
		{
			return Observable.FromEventPattern<BaseMessageEventArgs>(h => OnMessageReceived += h, h => OnMessageReceived -= h)
				.Where(args => args.EventArgs.Message is T)
				.Select(args => args.EventArgs.Message as T);
		}

		public void Listen()
		{
			if (_networkObserver != null)
				return;

			var client = new UdpClient();
			client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
			client.Client.Bind(new IPEndPoint(IPAddress.Any, _multicastPort));
			client.JoinMulticastGroup(_multicastAddress, 50);
			_networkObserverFactory = Observable.FromAsyncPattern(client.BeginReceive,
																  r =>
																  {
																	  var endpoint = new IPEndPoint(IPAddress.Any, 0);
																	  var data = client.EndReceive(r, ref endpoint);
																	  return data;
																  });

			_networkObserver = _networkObserverFactory.Invoke().Subscribe(OnReceive);
		}
	}
}

#endif